<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<style>
body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px; }

body > *:first-child {
  margin-top: 0 !important; }
body > *:last-child {
  margin-bottom: 0 !important; }

a {
  color: #4183C4; }
a.absent {
  color: #cc0000; }
a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0; }

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative; }

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  background: url() no-repeat 10px center;
  text-decoration: none; }

h1 tt, h1 code {
  font-size: inherit; }

h2 tt, h2 code {
  font-size: inherit; }

h3 tt, h3 code {
  font-size: inherit; }

h4 tt, h4 code {
  font-size: inherit; }

h5 tt, h5 code {
  font-size: inherit; }

h6 tt, h6 code {
  font-size: inherit; }

h1 {
  font-size: 28px;
  color: black; }

h2 {
  font-size: 24px;
  border-bottom: 1px solid #cccccc;
  color: black; }

h3 {
  font-size: 18px; }

h4 {
  font-size: 16px; }

h5 {
  font-size: 14px; }

h6 {
  color: #777777;
  font-size: 14px; }

p, blockquote, ul, ol, dl, li, table, pre {
  margin: 15px 0; }

hr {
  background: transparent url() repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0;
}

body > h2:first-child {
  margin-top: 0;
  padding-top: 0; }
body > h1:first-child {
  margin-top: 0;
  padding-top: 0; }
  body > h1:first-child + h2 {
    margin-top: 0;
    padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0; }

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0; }

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0; }

li p.first {
  display: inline-block; }
li {
  margin: 0; }
ul, ol {
  padding-left: 30px; }

ul :first-child, ol :first-child {
  margin-top: 0; }

dl {
  padding: 0; }
  dl dt {
    font-size: 14px;
    font-weight: bold;
    font-style: italic;
    padding: 0;
    margin: 15px 0 5px; }
    dl dt:first-child {
      padding: 0; }
    dl dt > :first-child {
      margin-top: 0; }
    dl dt > :last-child {
      margin-bottom: 0; }
  dl dd {
    margin: 0 0 15px;
    padding: 0 15px; }
    dl dd > :first-child {
      margin-top: 0; }
    dl dd > :last-child {
      margin-bottom: 0; }

blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

table {
  padding: 0;border-collapse: collapse; }
  table tr {
    border-top: 1px solid #cccccc;
    background-color: white;
    margin: 0;
    padding: 0; }
    table tr:nth-child(2n) {
      background-color: #f8f8f8; }
    table tr th {
      font-weight: bold;
      border: 1px solid #cccccc;
      margin: 0;
      padding: 6px 13px; }
    table tr td {
      border: 1px solid #cccccc;
      margin: 0;
      padding: 6px 13px; }
    table tr th :first-child, table tr td :first-child {
      margin-top: 0; }
    table tr th :last-child, table tr td :last-child {
      margin-bottom: 0; }

img {
  max-width: 100%; }

span.frame {
  display: block;
  overflow: hidden; }
  span.frame > span {
    border: 1px solid #dddddd;
    display: block;
    float: left;
    overflow: hidden;
    margin: 13px 0 0;
    padding: 7px;
    width: auto; }
  span.frame span img {
    display: block;
    float: left; }
  span.frame span span {
    clear: both;
    color: #333333;
    display: block;
    padding: 5px 0 0; }
span.align-center {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-center > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: center; }
  span.align-center span img {
    margin: 0 auto;
    text-align: center; }
span.align-right {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-right > span {
    display: block;
    overflow: hidden;
    margin: 13px 0 0;
    text-align: right; }
  span.align-right span img {
    margin: 0;
    text-align: right; }
span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left; }
  span.float-left span {
    margin: 13px 0 0; }
span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right; }
  span.float-right > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: right; }

code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px; }

pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent; }

.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }

pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }
  pre code, pre tt {
    background-color: transparent;
    border: none; }

sup {
    font-size: 0.83em;
    vertical-align: super;
    line-height: 0;
}
* {
	-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
    body {
        width: 854px;
        margin:0 auto;
    }
}
@media print {
	table, pre {
		page-break-inside: avoid;
	}
	pre {
		word-wrap: break-word;
	}
}
</style>
<title>IoC容器</title>

</head>
<body>
<h1>IoC容器</h1>

<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#basic-usage">基本用法</a></li>
<li><a href="#automatic-resolution">自动分辨</a></li>
<li><a href="#practical-usage">实际使用</a></li>
<li><a href="#service-providers">服务提供商</a></li>
<li><a href="#container-events">容器事件</a></li>
</ul>


<p><a name="introduction"></a></p>

<h2>简介</h2>

<p>Laravel 的反转控制容器是用来管理类依赖关系的强大的工具。依赖注入是一种删除硬编码类依赖的方法。相反，依赖关系将在运行时被注入，为依赖关系的实现能够轻易的改变提供更大的灵活性。</p>

<p>对构建一个大型的应用，理解 Laravel IoC 容器和理解 Laravel 核心代码本身一样是有必要的。</p>

<p><a name="basic-usage"></a></p>

<h2>基本用法</h2>

<p>有两种方式 IoC 容器能够解决依赖关系：通过闭包回调函数或以及自动分辨。我们首先将探讨闭包回调函数。首先，一个类型可以在容器内绑定：</p>

<p><strong>在容器内绑定一个类型</strong></p>

<pre><code>App::bind('foo', function($app)
{
    return new FooBar;
});
</code></pre>

<p><strong>在容器内解析一个类型</strong></p>

<pre><code>$value = App::make('foo');
</code></pre>

<p>当 <code>App::make</code> 函数被调用，闭包回调函数将被执行并返回结果。</p>

<p>有些时候，您可能希望在容器内绑定一些只被一次解析的内容，并且相同的实例应该在随后的调用中返回到容器：</p>

<p><strong>绑定一个共享类型的容器</strong></p>

<pre><code>App::singleton('foo', function()
{
    return new FooBar;
});
</code></pre>

<p>您可以使用 <code>instance</code> 函数绑定一个现有的对象实例到容器：</p>

<p><strong>绑定一个已有的实现到容器</strong></p>

<pre><code>$foo = new Foo;

App::instance('foo', $foo);
</code></pre>

<p><a name="automatic-resolution"></a></p>

<h2>自动分辨</h2>

<p>IoC 容器足够强大，能在许多场景中哦解析类而不需要任何配置。比如：</p>

<p><strong>解析一个类</strong></p>

<pre><code>class FooBar {

    public function __construct(Baz $baz)
    {
        $this-&gt;baz = $baz;
    }

}

$fooBar = App::make('FooBar');
</code></pre>

<p>注意尽管我们并没有在容器中注册 FooBar 类，容器仍然可以解析这个类，甚至自动注入 <code>Baz</code> 的依赖关系。</p>

<p>当一个类型没有在容器中绑定，它将使用 PHP 的反射机制检查类并且读取构造函数的类型提示。利用这些信息，容器能够自动构建一个类的实例。</p>

<p>但是，在某些情况下，一个类可能依赖于一个接口的实现，而不是一个具体的类。在这中情况下，<code>App::bind</code> 函数必须被用来通知容器注入哪一个接口：</p>

<p><strong>绑定一个接口</strong></p>

<pre><code>App::bind('UserRepositoryInterface', 'DbUserRepository');
</code></pre>

<p>现在考虑下面的控制器；</p>

<pre><code>class UserController extends BaseController {

    public function __construct(UserRepositoryInterface $users)
    {
        $this-&gt;users = $users;
    }

}
</code></pre>

<p>因为我们已经绑定 <code>UserRepositoryInterface</code> 到一个具体的类型，<code>DbUserRepository</code>将自动被注入到控制器当它被创建的时候。</p>

<p><a name="practical-usage"></a></p>

<h2>实际使用</h2>

<p>Laravel 提供了好几处场景使用 IoC 容器来为您的应用程序增加灵活性和可测试性。一个主要的例子是解析控制器。所有控制器通过 IoC 容器解析，意味着您能够在控制器构造函数中类型提示依赖关系，并且它们自动被注入。</p>

<p><strong>Type-Hinting 控制器依赖关系</strong></p>

<pre><code>class OrderController extends BaseController {

    public function __construct(OrderRepository $orders)
    {
        $this-&gt;orders = $orders;
    }

    public function getIndex()
    {
        $all = $this-&gt;orders-&gt;all();

        return View::make('orders', compact('all'));
    }

}
</code></pre>

<p>在这个例子中，<code>OrderRepository</code> 类将自动注入到控制器。这意味着当 <a href="/docs/testing">单元测试</a> 一个模拟，<code>OrderRepository</code> 可以被绑定到容器并且注入到控制器，允许无痛的数据库层交互。</p>

<p><a href="/docs/routing#route-filters">过滤器</a>, <a href="/docs/responses#view-composers">组件</a> 以及 <a href="/docs/events#using-classes-as-listeners">时间处理器</a> 都可以被 IoC container 解析。当注册它们，给出需要被使用的名字：</p>

<p><strong>其他 IoC 使用的例子</strong></p>

<pre><code>Route::filter('foo', 'FooFilter');

View::composer('foo', 'FooComposer');

Event::listen('foo', 'FooHandler');
</code></pre>

<p><a name="service-providers"></a></p>

<h2>服务提供商</h2>

<p>服务提供商是一个很好的方式在一个地方组织相关的 IoC 的注册。把他们作为应用程序中引导组件的一种方式。在服务提供商中，您可以注册一个定制的认证驱动，使用 Ioc 容器注册应用程序的类库，甚至设置一个自定义的 Artisan 命令。</p>

<p>事实上，大多数 Laravel 的核心组件包含服务提供商。所有应用程序中已注册的服务提供商在 <code>app/config/app.php</code> 配置文件的 <code>providers</code> 数组中列出。</p>

<p>创建一个服务提供商，请继承 <code>Illuminate\Support\ServiceProvider</code> 类并定义一个 <code>register</code> 函数：</p>

<p><strong>定义一个服务提供商</strong></p>

<pre><code>use Illuminate\Support\ServiceProvider;

class FooServiceProvider extends ServiceProvider {

    public function register()
    {
        $this-&gt;app-&gt;bind('foo', function()
        {
            return new Foo;
        });
    }

}
</code></pre>

<p>注意在 <code>register</code> 函数中，应用程序的 IoC 容器通过 <code>$this-&gt;app</code> 属性是可用的。一旦您已经创建了一个提供者，并且准备在应用程序中注册，请添加它到 <code>app</code> 配置的 <code>providers</code> 数组。</p>

<p>您也可以在程序运行时通过 <code>App::register</code> 函数注册一个服务提供商：</p>

<p><strong>程序运行时注册一个服务提供商</strong></p>

<pre><code>App::register('FooServiceProvider');
</code></pre>

<p><a name="container-events"></a></p>

<h2>容器事件</h2>

<p>容器每次解析一个对象时将触发一个事件。您可以通过使用 <code>resolving</code> 函数监听这个事件：</p>

<p><strong>注册一个解析监听器</strong></p>

<pre><code>App::resolving(function($object)
{
    //
});
</code></pre>

<p>注意被解析的对象将被传递给回调函数。</p>
</body>
</html>